{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e4341407-9c47-456b-a6d6-1960bac9d94b",
   "metadata": {},
   "source": [
    "FastAPI 支持创建含子依赖项的依赖项。\r\n",
    "\r\n",
    "并且，可以按需声明任意深度的子依赖项嵌套层级。\r\n",
    "\r\n",
    "FastAPI 负责处理解析不同深度的子依赖项。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d0fdb175-fd03-4745-9bc0-e2a98630ea73",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [24572]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:64803 - \"GET /items/?q=%E6%9D%8E%E5%9B%9B HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:64825 - \"GET /items/?last_query=%E5%BC%A0%E4%B8%89 HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:64853 - \"GET /items/?q=%E6%9D%8E%E5%9B%9B&last_query=%E5%BC%A0%E4%B8%89 HTTP/1.1\" 200 OK\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [24572]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import Depends, FastAPI\n",
    "app = FastAPI()\n",
    "\n",
    "def query_extractor(q: str | None = None):\n",
    "    return q\n",
    "\n",
    "def query_or_cookie_extractor(\n",
    "    q: str = Depends(query_extractor),\n",
    "    last_query: str | None = \"last query\",\n",
    "):\n",
    "    if not q:\n",
    "        return last_query\n",
    "    return q\n",
    "\n",
    "@app.get(\"/items/\")\n",
    "async def read_query(query_or_default: str = Depends(query_or_cookie_extractor)):\n",
    "    return {\"q_or_query\": query_or_default}\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be8d0b85-198a-4409-9455-ae3fcaf05217",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/?q=李四' \n",
    "res = requests.get(url) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"q_or_query\":\"李四\"}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a42069f1-29e3-4298-988e-188d45764af4",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/?last_query=张三' \n",
    "res = requests.get(url) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"q_or_query\":\"张三\"}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0719b636-9b7e-4e20-a79e-be75f069d0c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/?q=李四&last_query=张三' \n",
    "res = requests.get(url) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"q_or_query\":\"李四\"}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6f6a302-780f-430b-a83a-f6717b40fb56",
   "metadata": {},
   "source": [
    "注意，这里在路径操作函数中只声明了一个依赖项，即 query_or_cookie_extractor 。\r\n",
    "\r\n",
    "但 FastAPI 必须先处理 query_extractor，以便在调用 query_or_cookie_extractor 时使用 query_extractor 返回的结果。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3f96b1d0-ea9b-473b-b42f-414f2109f997",
   "metadata": {},
   "source": [
    "第一层依赖项query_extractor\n",
    "\n",
    "第二层依赖项query_or_cookie_extractor"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6af18fbb-f93f-43d5-b04b-3c884f79c37c",
   "metadata": {},
   "source": [
    "## 多次使用同一个依赖项"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4003cb18-73fc-4887-8682-7c4409dd3506",
   "metadata": {},
   "source": [
    "如果在同一个路径操作 多次声明了同一个依赖项，例如，多个依赖项共用一个子依赖项，FastAPI 在处理同一请求时，只调用一次该子依赖项。\r\n",
    "\r\n",
    "FastAPI 不会为同一个请求多次调用同一个依赖项，而是把依赖项的返回值进行「缓存」，并把它传递给同一请求中所有需要使用该返回值的「依赖项」。\r\n",
    "\r\n",
    "在高级使用场景中，如果不想使用「缓存」值，而是为需要在同一请求的每一步操作（多次）中都实际调用依赖项，可以把 Depends 的参数 use_cache 的值设置为 False :"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "801b40ab-0759-42ab-9852-ba8891ba3f72",
   "metadata": {},
   "outputs": [],
   "source": [
    "async def needy_dependency(fresh_value: str = Depends(get_value, use_cache=False)):\n",
    "    return {\"fresh_value\": fresh_value}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
